from image_utils import logging # 从image_utils.py中导入logging对象
import numpy as np


def adjust_contrast(image, contrast_factor):
    """
    调整图像的对比度
    :param image: 输入图像，numpy数组
    :param contrast_factor: 对比度调整因子，范围通常在0.0到3.0之间
                           0.0表示完全没有对比度（灰色图像）
                           1.0表示原始对比度
                           大于1.0表示增加对比度
    :return: 调整对比度后的图像
    """
    try:
        logging.info(f"开始调整图像对比度，调整因子：{contrast_factor}")
        
        # 将图像转换为浮点类型，以便于计算
        img_float = image.astype(float)
        
        # 计算图像的平均亮度
        mean_value = np.mean(img_float)
        
        # 应用对比度调整公式：(image - mean) * contrast_factor + mean
        adjusted_image = (img_float - mean_value) * contrast_factor + mean_value
        
        # 将像素值裁剪到有效范围内（0-255）
        adjusted_image = np.clip(adjusted_image, 0, 255)
        
        # 转换回原始数据类型
        result_image = adjusted_image.astype(image.dtype)
        
        logging.info("图像对比度调整完成")
        return result_image
    except Exception as e:
        logging.error(f"调整图像对比度时发生错误: {e}")
        raise ValueError(f"Error occurred while adjusting image contrast: {e}")


def adjust_brightness(image, brightness_factor):
    """
    调整图像的亮度
    :param image: 输入图像，numpy数组
    :param brightness_factor: 亮度调整因子，范围在0.0到2.0之间
                             0.0表示完全黑色图像
                             1.0表示原始亮度
                             2.0表示亮度增加一倍
    :return: 调整亮度后的图像
    """
    try:
        logging.info(f"开始调整图像亮度，调整因子：{brightness_factor}")
        
        # 将图像转换为浮点类型，以便于计算
        img_float = image.astype(float)
        
        # 应用亮度调整公式：image * brightness_factor
        adjusted_image = img_float * brightness_factor
        
        # 将像素值裁剪到有效范围内（0-255）
        adjusted_image = np.clip(adjusted_image, 0, 255)
        
        # 转换回原始数据类型
        result_image = adjusted_image.astype(image.dtype)
        
        logging.info("图像亮度调整完成")
        return result_image
    except Exception as e:
        logging.error(f"调整图像亮度时发生错误: {e}")
        raise ValueError(f"Error occurred while adjusting image brightness: {e}")


def invert_colors(image):
    """
    对图像进行反色处理（非运算）
    :param image: 输入图像，numpy数组（支持灰度图和彩色图）
    :return: 反色处理后的图像
    """
    try:
        logging.info("开始应用反色处理")
        
        # 验证输入有效性
        if not isinstance(image, np.ndarray):
            raise ValueError("输入必须是有效的numpy数组")
            
        # 对每个像素值执行255 - pixel操作
        inverted_image = 255 - image
        
        # 保持原数据类型
        if image.dtype != np.uint8:
            inverted_image = inverted_image.astype(image.dtype)
        
        logging.info("反色处理完成")
        return inverted_image
    except Exception as e:
        logging.error(f"应用反色处理时发生错误: {e}")
        raise ValueError(f"Error occurred while inverting colors: {e}")


def crop_image(image, crop_region):
    """
    裁剪图像
    :param image: 输入图像，PIL.Image对象
    :param crop_region: 裁剪区域,格式为(上,下,左,右)
    :return: 裁剪后的图像
    """
    try:
        logging.info(f"开始裁剪图像，裁剪区域,{crop_region}")
          # 从crop_region中提取上、下、左、右的坐标
        top, bottom, left, right = crop_region
        
        # 确保坐标在有效范围内
        height, width = image.shape[:2]
        top = max(0, top)
        left = max(0, left)
        bottom = min(height, bottom)
        right = min(width, right)
        
        # 直接使用切片操作，裁剪图像 image 生成裁剪后的图像 cropped_image
        cropped_image = image[top:bottom, left:right]
        
        return cropped_image
    except Exception as e:
        raise ValueError(f"Error occurred while cropping image: {e}")


def apply_global_threshold(image, threshold_value):
    """
    对图像应用全局阈值处理
    :param image: 输入图像，numpy数组（应为灰度图像）
    :param threshold_value: 阈值，范围在0到255之间
    :return: 阈值处理后的二值图像
    """
    try:
        # 验证输入图像是否为灰度图
        if len(image.shape) > 2 and image.shape[2] > 1:
            raise ValueError("输入图像必须是灰度图像")
            
        logging.info(f"开始应用全局阈值处理，阈值：{threshold_value}")
        
        # 将图像转换为numpy数组（如果不是的话）
        img_array = np.array(image)
        
        # 应用全局阈值
        # 创建一个与原图相同形状的全零数组（表示黑色）
        binary_image = np.zeros_like(img_array)
        
        # 将大于等于阈值的像素设为255（表示白色）
        binary_image[img_array >= threshold_value] = 255
        
        logging.info("全局阈值处理完成")
        return binary_image
    except Exception as e:
        logging.error(f"应用全局阈值时发生错误: {e}")
        raise ValueError(f"Error occurred while applying global threshold: {e}")


def shift_difference_edge(image, shift_pixels):
    """
    通过平移图像并与原图相减来检测边缘
    :param image: 输入图像，numpy数组（应为灰度图像）
    :param shift_pixels: 平移的像素数量，正值表示向右移动，负值表示向左移动
    :return: 边缘检测后的图像
    """
    try:
        # 验证输入图像是否为灰度图
        if len(image.shape) > 2 and image.shape[2] > 1:
            raise ValueError("输入图像必须是灰度图像")
            
        logging.info(f"开始应用移动差分边缘检测，平移像素：{shift_pixels}")
        
        # 将图像转换为numpy数组（如果不是的话）
        img_array = np.array(image)
        height, width = img_array.shape[:2]
        
        # 创建一个与原图相同形状的全零数组
        edge_image = np.zeros_like(img_array)
        
        if shift_pixels == 0:
            # 如果平移为0，则直接返回全黑图像
            return edge_image
        
        # 根据平移方向和像素数进行操作
        if shift_pixels > 0:  # 向右移动
            # 原图与右移后的图像相减
            edge_image[:, shift_pixels:] = np.abs(
                img_array[:, shift_pixels:] - img_array[:, :-shift_pixels]
            )
        else:  # 向左移动 (shift_pixels < 0)
            shift_pixels = abs(shift_pixels)
            # 原图与左移后的图像相减
            edge_image[:, :-shift_pixels] = np.abs(
                img_array[:, :-shift_pixels] - img_array[:, shift_pixels:]
            )
        
        # 将结果转换为8位无符号整数类型（范围0-255）
        edge_image = edge_image.astype(np.uint8)
        
        logging.info("移动差分边缘检测完成")
        return edge_image
    except Exception as e:
        logging.error(f"应用移动差分边缘检测时发生错误: {e}")
        raise ValueError(f"Error occurred while applying shift difference edge detection: {e}")

